November 24, 2021
2021년 3월 초기에 작성했던 문서라 현재 AWS 콘솔과는 달라질 수 있다는점 꼭 확인해주세요!
EC2 → Auto Scaling → Launch Configurations 에서 시작 구성 생성
#! /bin/bash
cd /home/ubuntu
./start.sh
# codeDeploy 실행
# 확인 결과 AMI에서 codeDeploy-agent가 설치되었다면 실행하지 않아도 자동으로 실행합니다.
sudo ./install auto
원본 인스턴스에서 필요한 환경
IP 주소 유형
그룹 생성하기
해당 그룹에서 새로운 인스턴스를 확인할 수 있습니다.
AWS CodeDeploy에서 생성합니다.
배포 설정
여기까지 왔으면 AWS Console로 생성은 모두 마쳤습니다. 마지막으로 해당 프로젝트 루트에서 쉘스크립트, appspec.yml을 설정합니다.
- name: Code Deploy
run: aws deploy create-deployment --application-name cicdtest --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name cicd-bluegreen --s3-location bucket=cicdtestsunny,bundleType=zip,key=build.zip
--application-name
: AWS CodeDeploy 애플리케이션 이름--deployment-config-name
: 배포 구성(CodeDeploy의 배포구성)--deployment-group-name
: 배포 그룹 이름--s3-location
: s3 버킷 이름, 빌드 타입, 빌드 파일이름 지정version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/myapp # 파일 배포 경로
permissions:
- object: /home/ubuntu/
owner: ubuntu
group: ubuntu
mode: 755
hooks:
BeforeInstall:
- location: beforeInstall.sh # 배포 이전
timeout: 60
runas: root
AfterInstall:
- location: deploy.sh
timeout: 60
runas: root
AWS CodeDeploy는 이전 파일이 존재일 경우 에러가 발생합니다.
The deployment failed because a specified file already exists at this location
CodeDeploy는 파일 덮어쓰기가 불가능하기 때문에 다음 레퍼런스처럼 삭제하고 다시 배포하는 형식을 취하면 됩니다.
#!/usr/bin/env bash
REPOSITORY=/home/ubuntu/
if [ -d $REPOSITORY/myapp ]; then
rm -rf $REPOSITORY/myapp
fi
mkdir -vp $REPOSITORY/myapp
#!/usr/bin/env bash
REPOSITORY=/home/ubuntu/myapp
APP_NAME=demo
echo "> pid 확인"
CURRENT_PID=$(pgrep -fl $APP_NAME | grep java | awk '{print $1}')
echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
echo "> 현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> 새 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)
echo "> Jar name: JAR_NAME"
echo "> $JAR_NAME에 실행 권한 추가"
chmod +x $JAR_NAME
echo "> $JAR_NAME 배포"
nohup java -jar $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
배포스크립트는 해당 프로젝트마다 다르니 꼭 쉘스크립트는 프로젝트 환경 확인하시고 작성해주세요.
여기까지 작성하느라 고생하셨습니다. 이제 테스트를 해보겠습니다.
우선 간단한 Spring 컨트롤러를 만듭니다.
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.net.InetAddress;
import java.net.UnknownHostException;
@RestController
public class HelloController {
@GetMapping("/hello")
public String getUser() {
String hostName, ipaddress;
try {
hostName = InetAddress.getLocalHost().getHostName();
ipaddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostName = new StringBuilder("Error : ").append(e.getLocalizedMessage()).toString();
ipaddress = "";
}
return "hostName : " + hostName + " ipaddress : " + ipaddress + " pland가 조아";
}
@GetMapping("/hi")
public String hi() {
String hostName;
String ipaddress;
try {
hostName = InetAddress.getLocalHost().getHostName();
ipaddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
hostName = new StringBuilder("Error : ").append(e.getLocalizedMessage()).toString();
ipaddress = "";
}
return "Hi" + hostName + " :: " + ipaddress;
}
}
hostname, piaddress를 생성하여 auto scaling과 load balancer가 제대로 작동하는지 확인할 수 있는 컨트롤러 입니다.
커밋하고 실행!
다음과 같이 인스턴스 생성 삭제를 확인할 수 있습니다.
ELB Round Robin 방식으로 새로고침할 때마다 ip가 달라지는 모습을 확인할 수 있습니다.
기존의 Classic Load Balancer는 스프링에서 처리할 때 HTTP로 요청을 받아 처리하는 바람에 OAuth2 로그인 적용시 HTTPS로 요청보냈다가 HTTP로 받을 수도 있었습니다. 그래서 스프링부트의 내부톰캣 설정으로 다음과 같은 처리가 필요합니다.
server.tomcat.remoteip.protocol-header=x-forwarded-proto
그러나 현재 사용하고 있는 Application Load Balancer는 전부 HTTPS로 처리하기 때문에 스프링 톰캣 설정을 추가할 필요가 없습니다.
여기까지 따라오시느라 고생많으셨습니다!!
ELB로 무중단 배포를 성공적으로 이뤄지길 바랍니다!!😆
Nginx와는 다르게 AWS 인프라 하나로 다 처리할 수 있어 관리할 때는 편합니다.
다만, 시간이 Nginx 배포보다 훨씬 느리고 비용도 더 많이 들어 스타트업이나 작은 규모의 회사에서는 사용할 가치가 있는지 고려를 해야할 듯 합니다.
특히 배포 테스트할 때 너무 오래 걸려 힘들었네요😭
DOWNLOAD_SOURCE 실패할 때
CLIENT_ERROR: Get "[<https://github.com/pland-sunny/cicdtest/info/refs?service=git-upload-pack>](<https://github.com/pland-sunny/cicdtest/info/refs?service=git-upload-pack>)": dial tcp 52.78.231.108:443: i/o timeout for primary source
→ NAT Gateway 필요합니다.
→ IAM을 권한 받기전에 AWS CodeDeploy를 실행했기 때문입니다.
→ sudo service codedeploy-agent restart
를 시도해볼것!
codedeploy The specified key does not exist
해당 파일이 없다는 뜻으로 S3에서 파일이름, 확장자 확인해야합니다.
The deployment failed because no instances were found in your blue fleet.
blue 인스턴스가 생성하지 못함 → 확인 결과 2b의 서브넷은 t2.micro 생성하도록 설정했기 때문에 auto-scaling에서 생성하지 못하여 에러 발생합니다.
The deployment failed because a specified file already exists at this location